﻿using Red.EngineData.Protocol.Interop;
using System;
using System.Collections.Concurrent;
using System.Windows.Threading;

namespace Red.Controls.Utils
{
    /// <summary>
    /// Pulls updates from the update queue on UI thread instead of pushing them to the UI thread.
    /// This makes the interop/engine data really fast.
    /// </summary>
    public class PullActionResponseScheduler : IViewUpdateScheduler
    {
        /// <summary>
        /// Queue of handlers for responses to update.
        /// </summary>
        ConcurrentQueue<ViewUpdateEventHandler> _handlersToUpdate = new ConcurrentQueue<ViewUpdateEventHandler>();

        /// <summary>
        /// UI thread timer.
        /// </summary>
        DispatcherTimer _timer;

        /// <summary>
        /// Constructs.
        /// </summary>
        public PullActionResponseScheduler()
        {
            _timer = new DispatcherTimer();
            _timer.Interval = new TimeSpan( 10 );
            _timer.Tick += OnTick;
            _timer.IsEnabled = true;
        }

        /// <summary>
        /// Schedules.
        /// </summary>
        public void Schedule( ViewUpdateEventHandler handler )
        {
            _handlersToUpdate.Enqueue( handler );
        }

        /// <summary>
        /// Called on UI thread, pulls updates from the queue and executes them.
        /// You can introduce throttling here.
        /// </summary>
        private void OnTick( object sender, EventArgs e )
        {
            while ( _handlersToUpdate.IsEmpty == false )
            {
                ViewUpdateEventHandler handler;
                if ( _handlersToUpdate.TryDequeue( out handler ) )
                {
                    handler();
                }
            }
        }
    }
}
